﻿using Coolzon.Common;
using Coolzon.Web.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Coolzon.UI.ViewerApp
{
    /// <summary>
    /// SplashWindow.xaml 的交互逻辑
    /// </summary>
    public partial class SplashWindow : Window
    {
        private Thread _thread;
        private AppInfo _appInfo;
        public bool IsContinueRunning { get; private set; }
        private bool _isCheckVersion;

        public SplashWindow(bool IsCheckVersion, AppInfo appInfo)
        {
            InitializeComponent();
            _isCheckVersion = IsCheckVersion;
            this._appInfo = appInfo;

            //版本信息
            this._versionInfo.Text = "V" + App.XCurrent.AppInfo.Version.ToString(3);

            this.Loaded += OnSplashWindowLoaded;
        }

        void OnSplashWindowLoaded(object sender, RoutedEventArgs e)
        {
            _thread = new Thread(Running);
            _thread.Start();
        }

        private void Running()
        {
            IsContinueRunning = ConfigLoader.Load();
            //// for test
            //Config.Current.DefaultSolution = "DemoV2";

            if (IsContinueRunning)
            {
                Logger.InitByLogDirectory(Config.GetLogDirectory());
                IsContinueRunning = Startup.Run();
            }

            // 读取本地的组件列表
            List<Library> libraries = new List<Library>();
            IsContinueRunning = LoadLibraries(libraries);

            if (IsContinueRunning)
            {
                // 从服务器上获取library信息，并下载最新的
                List<Library> librariesOnServer = Coolzon.UI.Common.WebProxies.WebProxy.Instance.GetLibraries();
                IsContinueRunning = SyncLibraries(libraries, librariesOnServer);
            }

            if (IsContinueRunning && libraries.Count == 0)
            {
                // 重新加载Library
                IsContinueRunning = LoadLibraries(libraries);
            }

            if (IsContinueRunning)
            {
                try
                {
                    UI.Core.PartLibraryManager.Initiate(libraries);
                }
                catch(Exception ex)
                {
                    Logger.ErrorToTag("Startup", string.Format("PartLibraryManager Initiate出错,ex:{0}", ex));
                    IsContinueRunning = false;
                }
            }

            this.Dispatcher.Invoke(() =>
            {
                this.DialogResult = IsContinueRunning;
            });
        }

        public static bool LoadLibraries(List<Library> libraries)
        {
            if (!Directory.Exists(Config.GetLibrariesDirectory()))
            {
                // directory is not exist
                return true;
            }

            DirectoryInfo[] libraryDirecties = new DirectoryInfo(Config.GetLibrariesDirectory()).GetDirectories();
            foreach (var libraryDirectory in libraryDirecties)
            {
                string libraryJsonFilepath = System.IO.Path.Combine(libraryDirectory.FullName, "library.json");
                if (File.Exists(libraryJsonFilepath))
                {
                    try
                    {
                        Web.Models.Library library = Coolzon.Common.Config.JsonConfigUtil.LoadFromFile<Web.Models.Library>(libraryJsonFilepath);
                        library.AbsoluteDirectory = string.Format("{0}\\", libraryDirectory.FullName);
                        bool isNeedLoad = false;
                        bool isHasSameName = false;
                        for (int libIndex = 0; libIndex < libraries.Count; libIndex++)
                        {
                            if (string.Equals(libraries[libIndex].Name, library.Name, StringComparison.CurrentCultureIgnoreCase))
                            {
                                isHasSameName = true;
                                if (libraries[libIndex].GetVersion() < library.GetVersion())
                                {
                                    Logger.Info(string.Format("发现library:{0} {1},替换{2} {3}", library.Name, library.Version, libraries[libIndex].Name, libraries[libIndex].Version));
                                    libraries[libIndex] = library;
                                    isNeedLoad = true;
                                    break;
                                }
                                else
                                {
                                    isNeedLoad = false;
                                }
                            }
                        }

                        if (!isHasSameName)
                        {
                            libraries.Add(library);
                            Logger.Info(string.Format("发现library:{0} {1}", library.Name, library.Version));
                            isNeedLoad = true;
                        }

                        if (!isNeedLoad)
                        {
                            continue;
                        }

                        FileInfo[] files = libraryDirectory.GetFiles();
                        int existDLLFileCount = 0;
                        foreach (var file in files)
                        {
                            if (string.Equals(file.Name, library.File, StringComparison.CurrentCultureIgnoreCase))
                            {
                                existDLLFileCount++;
                            }
                            else
                            {
                                foreach (var dependencyFile in library.Dependencies)
                                {
                                    if (string.Equals(file.Name, dependencyFile.File, StringComparison.CurrentCultureIgnoreCase))
                                    {
                                        existDLLFileCount++;
                                        break;
                                    }
                                }
                            }
                        }

                        if (existDLLFileCount < library.Dependencies.Length + 1)
                        {
                            throw new Exception(string.Format("library:{0}中定义的DLL文件并不是全部存在!", library.Name));
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex.ToString());
                        return false;
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// 如果更新了组件库那么会将localLibraries清空,count=0
        /// </summary>
        /// <param name="localLibraries"></param>
        /// <param name="serverLibraries"></param>
        /// <returns></returns>
        public static bool SyncLibraries(List<Library> localLibraries, List<Library> serverLibraries)
        {
            bool hasUpdate = false;
            foreach (var serverLib in serverLibraries)
            {
                bool isNeedDownload = true;
                foreach (var localLib in localLibraries)
                {
                    if(string.Equals(serverLib.Name, localLib.Name, StringComparison.CurrentCultureIgnoreCase)
                        && serverLib.GetVersion() <= localLib.GetVersion())
                    {
                        isNeedDownload = false;
                        break;
                    }
                }

                if (isNeedDownload)
                {
                    hasUpdate = true;
                    string directory = string.Format("{0}{1} {2}\\", Config.GetLibrariesDirectory(), serverLib.Name, serverLib.Version);
                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }
                    List<string> files = new List<string>();
                    files.Add("Library.json");
                    files.Add(serverLib.File);
                    foreach(var dependency in serverLib.Dependencies)
                    {
                        files.Add(dependency.File);
                    }

                    foreach (var file in files)
                    {
                        string filepath = string.Format("{0}{1}", directory, file);
                        string url = Config.GetLibraryFileDownloadUrl(serverLib.Name, serverLib.Version, file);
                        try
                        {
                            new System.Net.WebClient().DownloadFile(url, filepath);

                            Logger.InfoToTag("Startup", string.Format("下载文件到:{0}", filepath));
                        }
                        catch (Exception ex)
                        {
                            // 
                            Logger.Error(string.Format("下载文件:{0}到:{1}失败,ex:{2}", url, filepath, ex));
                            return false;
                        }
                    }
                }
            }

            if (hasUpdate)
            {
                localLibraries.Clear();
            }
            return true;
        }

        /// <summary>
        /// 拖动窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Grid_MouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }

        private static object GetEventValue(object objectHasEvents, string eventName)
        {
            if (objectHasEvents == null)
            {
                return null;
            }

            try
            {
                EventInfo[] events = objectHasEvents.GetType().GetEvents(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                if (events == null || events.Length < 1)
                {
                    return null;
                }

                for (int i = 0; i < events.Length; i++)
                {
                    EventInfo ei = events[i];

                    if (ei.Name == eventName)
                    {
                        //FieldInfo[] fields = ei.DeclaringType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                        FieldInfo fi = ei.DeclaringType.GetField("_AssemblyResolve", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                        if (fi != null)
                        {
                            return fi.GetValue(objectHasEvents);
                        }
                    }
                }
            }
            catch
            {
            }
            return null;
        }
    }
}
